<?php

namespace app\common\library\xmwechat\offiaccount;

use app\admin\model\xmwechat\offiaccount\Autoreply;
use app\admin\model\xmwechat\offiaccount\Material;
use app\common\library\xmwechat\SingletonTrait;
use app\common\library\xmwechat\WechatService;
use EasyWeChat\Kernel\Exceptions\BadRequestException;
use EasyWeChat\Kernel\Exceptions\InvalidArgumentException;
use EasyWeChat\Kernel\Exceptions\RuntimeException;
use EasyWeChat\OfficialAccount\Application;
use Psr\Http\Message\ResponseInterface;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\exception\HttpResponseException;
use think\facade\Log;
use think\Response;

/**
 * 消息推送
 */
class MessageService extends WechatService
{
    protected ?Application $app;
    protected string $accessToken;

    use SingletonTrait;

    public function __construct()
    {
        parent::__construct();
        if (empty($this->offiAccountConfig['app_id']) || empty($this->offiAccountConfig['secret'])) {
            $this->result('请配置公众号appid或secret');
        }
        $this->app         = new Application([
            'app_id'  => $this->offiAccountConfig['app_id'],
            'secret'  => $this->offiAccountConfig['secret'],
            'token'   => $this->offiAccountConfig['server_token'],
            'aes_key' => $this->offiAccountConfig['encoding_aes_key'],
        ]);
        $accessToken       = $this->app->getAccessToken();
        $this->accessToken = $accessToken->getToken();
    }

    /**
     * 微信开发文档 https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_event_pushes.html
     * @return ResponseInterface
     * @throws InvalidArgumentException
     * @throws BadRequestException
     * @throws RuntimeException
     * @throws \ReflectionException
     * @throws \Throwable
     * @author jsjxsz <QQ:1365962177>
     */
    public function messageServe(): ResponseInterface
    {
        $server = $this->app->getServer();
        // 自定义菜单click事件
        // {"ToUserName":"gh_3fd79f90b5af","FromUserName":"oluKa548P2NdCeiEbvlAomQxLKfM","CreateTime":"1693377845","MsgType":"event","Event":"CLICK","EventKey":"fq99mlqge3"}
        $server->addEventListener('CLICK', function ($message) {
            Log::info('event-message-CLICK' . json_encode($message,JSON_UNESCAPED_UNICODE));
            $eventKey = $message['EventKey'];
            return $this->getReplyContentByEvent('click', $eventKey);
        });
        // 订阅事件
        // {"ToUserName":"gh_3fd79f90b5af","FromUserName":"oluKa548P2NdCeiEbvlAomQxLKfM","CreateTime":"1693377844","MsgType":"event","Event":"subscribe","EventKey":""}
        $server->addEventListener('subscribe', function ($message) {
            Log::info('event-message-subscribe' . json_encode($message,JSON_UNESCAPED_UNICODE));
            return $this->getReplyContentByEvent('subscribe');
        });

        // 接收普通消息
        $server->addMessageListener('text', function ($message) {
            Log::info('接收普通消息text-message' . json_encode($message,JSON_UNESCAPED_UNICODE));
            return $this->getReplyContentByMessage($message['Content']);
        });

        return $server->serve();

    }

    /**
     * 事件消息回复内容
     * @param $event
     * @return array|string
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     * @author jsjxsz <QQ:1365962177>
     */
    public function getReplyContentByEvent($event, $eventKey = ''): array|string
    {
        if ($event == 'subscribe') {
            // 订阅事件回复内容
            $autoreply = Autoreply::where('type', 'follow')->where('status', 1)->find();
            if ($autoreply['msg_type'] == 'text') {
                return htmlspecialchars_decode($autoreply['reply_content']);
            } elseif ($autoreply['msg_type'] == 'image') {
                $content = json_decode($autoreply['reply_content'], true);
                return [
                    'MsgType' => 'image',
                    'Image'   => [
                        'MediaId' => $content['media_id'],
                    ],
                ];
            } elseif ($autoreply['msg_type'] == 'voice') {
                $content = json_decode($autoreply['reply_content'], true);
                return [
                    'MsgType' => 'voice',
                    'Voice'   => [
                        'MediaId' => $content['media_id'],
                    ],
                ];
            } elseif ($autoreply['msg_type'] == 'video') {
                $content = json_decode($autoreply['reply_content'], true);
                return [
                    'MsgType' => 'video',
                    'Video'   => [
                        'MediaId'     => $content['media_id'],
                        'Title'       => $content['name'],
                        'Description' => $content['description'],
                    ],
                ];
            } elseif ($autoreply['msg_type'] == 'news') {
                $content = json_decode($autoreply['reply_content'], true);
                return [
                    'MsgType'  => 'news',
                    'Articles' => [
                        'item' => [
                            'Title'       => $content['title'],
                            'Description' => $content['digest'],
                            'PicUrl'      => $content['show_cover_pic'],
                            'Url'         => $content['url'],
                        ]
                    ],
                ];
            } else {
                return $this->getDefaultReply();
            }
        } else if ($event == 'click') {
            $content = Material::where('event_key', $eventKey)->value('content');
            return htmlspecialchars_decode($content);
        } else {
            return $this->getDefaultReply();
        }
    }

    // 普通消息获取回复内容
    public function getReplyContentByMessage($content)
    {
        $autoreply = Autoreply::where('keyword', $content)->where('status', 1)->find();
        if (!empty($autoreply)) {
            $msg_type = $autoreply['msg_type'];
            if ($msg_type == 'text') {
                return htmlspecialchars_decode($autoreply['reply_content']);
            } elseif ($msg_type == 'image') {
                $content = json_decode($autoreply['reply_content'], true);
                return [
                    'MsgType' => 'image',
                    'Image'   => [
                        'MediaId' => $content['media_id'],
                    ],
                ];
            } elseif ($msg_type == 'voice') {
                $content = json_decode($autoreply['reply_content'], true);
                return [
                    'MsgType' => 'voice',
                    'Voice'   => [
                        'MediaId' => $content['media_id'],
                    ],
                ];
            } elseif ($msg_type == 'video') {
                $content = json_decode($autoreply['reply_content'], true);
                return [
                    'MsgType' => 'video',
                    'Video'   => [
                        'MediaId'     => $content['media_id'],
                        'Title'       => $content['name'],
                        'Description' => $content['description'],
                    ],
                ];
            } elseif ($msg_type == 'news') {
                $content = json_decode($autoreply['reply_content'], true);
                return [
                    'MsgType'  => 'news',
                    'Articles' => [
                        'item' => [
                            'Title'       => $content['title'],
                            'Description' => $content['digest'],
                            'PicUrl'      => $content['show_cover_pic'],
                            'Url'         => $content['url'],
                        ]
                    ],
                ];
            } else {
                return $this->getDefaultReply();
            }
        } else {
            return $this->getDefaultReply();
        }

    }

    /**
     * 默认回复
     * @return mixed
     * @author jsjxsz <QQ:1365962177>
     */
    public function getDefaultReply(): mixed
    {
        $content = Autoreply::where('type', 'default')->where('status', 1)->value('reply_content');
        return htmlspecialchars_decode($content);
    }


    /**
     * @param array $params
     * @return bool
     * @author jsjxsz <QQ:1365962177>
     */
    public function checkSignature(array $params): bool
    {
        $offiAccount  = config('xmwechat')['offiAccount'];
        $server_token = $offiAccount['server_token'];
        $tmpArr       = array($server_token, $params['timestamp'], $params['nonce']);
        sort($tmpArr, SORT_STRING);
        $tmpStr = implode($tmpArr);
        $tmpStr = sha1($tmpStr);
        if ($tmpStr == $params['signature']) {
            return true;
        } else {
            return false;
        }
    }

}